home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma1.arc / MSCMD.ASM next >
Assembly Source File  |  1986-02-13  |  37KB  |  1,311 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSCMD -- COMND module for MS-Kermit
  4.  
  5. ; Update 22 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13. ; This version has machine-dependent code for both IBM PCs and DEC Rainbows
  14.  
  15.     PUBLIC comnd, cmcfrm, prserr, repars, cmgtch, drives, comand, fcbcpy
  16.  
  17.     INCLUDE MsDefs.H
  18.  
  19. DataS    SEGMENT    PUBLIC 'DataS'
  20.  
  21.     extrn    flags:byte, trans:byte, fcb:byte, DTA:byte
  22.     extrn    taklev:byte, takadr:word, dosnum:byte, OldStk:WORD
  23.     EXTRN    PC_Type:BYTE, In_menu_mode:BYTE
  24.  
  25. comand    cmdinfo    <>
  26. cmer00  DB '? Program error   Invalid COMND call',cr,lf,'$'
  27. cmer01  DB '? Ambiguous',cr,lf,'$'
  28. cmer02  DB '? Illegal input file spec',cr,lf,'$'
  29. cmer03    DB '? Invalid command',cr,lf,'$'
  30. cmer04    DB '? Invalid command or operand',cr,lf,'$'
  31. cmer06    DB '? Wildcard not allowed',cr,lf,'$'
  32. cmer07    DB '? Invalid drive specificaton',cr,lf,'$'
  33. cmin00  DB ' Confirm with carriage return$'
  34. cmin01    DB ' One of the following:',cr,lf,'$'
  35.  
  36. F5_str    DB '<F5>',cr,lf,'$'
  37. DO_str    DB '<Do>',cr,lf,'$'
  38.  
  39. cmthlp    DW 0            ; Text of help message for random input
  40. drives    DB 0            ; How many drives we have. [21a]
  41. crlf    DB cr,lf,'$'
  42. ctcmsg    DB '^C', Cr, Lf, '$'
  43. prsp    DB ' $'            ; Print a space
  44. hlpmsg    DW 0            ; Address of help message
  45. spchar    DB 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  46.     DB 3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
  47. spclen    equ    $-spchar
  48. spchar2    DB 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  49.     DB 7BH,7DH,5FH,5EH,7EH,60H
  50. spc2len    equ    $-spchar2
  51. escspc    DB 10O,' ',10O,'$'    ; Clear escape
  52. clrspc  DB ' ',10O,'$'      ; Clear space
  53. filbuf  DB 60H DUP(?)        ; Character buffer
  54. tbuff    DB 80  DUP(?)
  55. cmdstk    DW ?
  56.  
  57. ; Parallel tables used to turn keypad function keys into binary ASCII values
  58.  
  59. Sensible_func_keys db  2fh,32h,35h,38h,3bh,3eh,41h,44h,47h,4ah,4dh,50h,53h,56h
  60. To_ASCII_scan_codes db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,2dh,2ch,2eh,0dh
  61. Func_table_length EQU    $ - To_ASCII_scan_codes
  62.  
  63. DataS    ENDS
  64.  
  65.  
  66. Code    SEGMENT    PUBLIC
  67.  
  68.     extrn    dodel:near, ctlu:near, cmblnk:near, locate:near, takrd:near
  69.     extrn    clearl:near, KrmRet:NEAR, Telnet2:NEAR, Beep:NEAR
  70.     EXTRN Quick_Push:NEAR, Quick_Menu:NEAR
  71.     assume    cs:code,ds:datas,es:datas
  72.  
  73. ;       This routine parses the specified function in AH. Any additional
  74. ;       information is in DX and BX
  75. ;       Returns +1 on success
  76. ;               +4 on failure (assumes a JMP follows the call)
  77.  
  78. CMND    PROC NEAR
  79. comnd:  mov comand.cmstat,ah    ; Save what we are presently parsing
  80.     mov cmdstk,sp        ; save stack ptr locally
  81.         call cminbf      ; Get chars until an action or a erase char
  82.     mov ah,comand.cmstat    ; Restore 'ah' for upcoming checks
  83.         cmp ah,cmcfm     ; Parse a confirm?
  84.         jz cmcfrm        ; Go get one
  85.         cmp ah,cmkey     ; Parse a keyword?
  86.     jnz cm1
  87.         jmp cmkeyw        ; Try and get one
  88. cm1:    cmp ah,cmifi        ; Parse an input file spec?
  89.     jnz cm2
  90.     jmp cmifil        ; Go get one
  91. cm2:    cmp ah,cmofi        ; Output file spec?
  92.     jnz cm3
  93.     jmp cmofil        ; Go get one
  94. cm3:    cmp ah,cmtxt        ; Parse arbitrary text.   [8]
  95.     jnz cm4
  96.     jmp cmtext
  97. cm4:    mov ah,prstr        ; Else give error
  98.     mov dx,offset cmer00    ; "?Unrecognized COMND call"
  99.     int dos
  100.     ret
  101.  
  102. ; This routine gets a confirm
  103.  
  104. cmcfrm: call cmgtch        ; Get a char
  105.     cmp ah,0        ; Is it negative (a terminator; a space or
  106.                 ; a tab will not be returned here as they
  107.                 ; will be seen as leading white space.)
  108.         js cmcfr0
  109.         ret          ; If not, return failure
  110. cmcfr0: and ah,7FH           ; Turn off the minus bit
  111.         cmp ah,esc           ; Is it an escape?
  112.         jne cmcfr2
  113.         mov ah,conout
  114.         mov dl,bell      ; Get a bell
  115.         int dos
  116.         mov ah,0
  117.         mov comand.cmaflg,ah    ; Turn off the action flag
  118.         mov bx,comand.cmcptr    ; Move the pointer to before thee scape
  119.         dec bx
  120.         mov comand.cmcptr,bx
  121.         mov comand.cmdptr,bx
  122.         dec comand.cmccnt       ; Decremrnt the char count
  123.         jmp cmcfrm       ; Try again
  124. cmcfr2: cmp ah,'?'       ; Curious?
  125.         jne cmcfr3
  126.         mov ah,prstr     ; Print something useful
  127.         mov dx,offset cmin00
  128.         int dos
  129.         mov ah,prstr
  130.         mov dx,offset crlf      ; Print a crlf
  131.         int dos
  132.         mov ah,prstr
  133.         mov dx,comand.cmprmp    ; Reprint the prompt
  134.         int dos
  135.         mov bx,comand.cmdptr    ; Get the pointer into the buffer
  136.         mov ah,'$'       ; Put a $ there for printing
  137.         mov [bx],ah
  138.         mov bx,comand.cmcptr
  139.         dec bx        ; Decrement & save the buffer pointer
  140.         mov comand.cmcptr,bx
  141.         mov ah,prstr
  142.         mov dx,offset comand.cmdbuf
  143.         int dos
  144.         mov ah,0            ; Turn off the action flag
  145.         mov comand.cmaflg,ah
  146.         jmp repars       ; Reparse everything
  147.  
  148. cmcfr3: cmp ah,ff            ; Is it a form feed?
  149.         jne cmcfr4
  150.         call cmblnk      ; If so blank the screen
  151. cmcfr4: jmp rskp
  152.  
  153. ;       This routine parses a keyword from the table pointed
  154. ;       to in DX.  The format of the table is as follows:
  155. ;
  156. ;       addr:   DB n       ; Where n is the # of entries in the table
  157. ;               DB m       ; M is the size of the keyword
  158. ;               DB 'string$' ; Where string is the keyword
  159. ;               DW ab      ; Where ab is data to be returned
  160. ;
  161. ;       The keywords must be in alphabetical order
  162.  
  163.  
  164. cmkeyw: mov comand.cmhlp,bx     ; Save the help
  165.         mov comand.cmptab,dx    ; Save the beginning of keyword table
  166.         mov bx,dx
  167.         mov ch,[bx]      ; Get number of entries in table
  168.         inc bx
  169.     mov dx,comand.cmdptr    ; Save command pointer
  170.     mov comand.cmsptr,dx    ; Save pointer's here
  171. cmky1:  cmp ch,0        ; Any commands left to check?
  172.         jne cmky2
  173.     jmp cmky41        ; no, go complain
  174. cmky2:  dec ch
  175.     mov cl,0        ; Keep track of how many chars read in so far
  176.         call cmgtch      ; Get a char
  177.         cmp ah,0        ; Do we have a terminator?
  178.         jns cmky2x 
  179.     jmp cmky4        ; Negative number means we do
  180. cmky2x: inc bx        ; Point to first letter of keyword
  181.     inc cl            ; Read in another char
  182.         mov al,[bx]                   
  183.         cmp ah,'a'       ; Less than a?
  184.         jl cmky21        ; If so, don't capitalize
  185.         cmp ah,'z'+1     ; More than z?
  186.         jns cmky21
  187.         and ah,137O      ; Capitalize the letter
  188. cmky21: cmp ah,al
  189.     je cmky3
  190.     jg cmky2y
  191.         jmp cmky41       ; Fail if ah preceeds al alphabetically
  192. cmky2y: jmp cmky6        ; Not this keyword - try the next
  193. cmky3:  inc bx        ; We match here, how 'bout next char?
  194.         mov al,[bx]
  195.         cmp al,'$'        ; End of keyword?
  196.     jne cmky3x
  197.         jmp cmky7        ; Succeed
  198. cmky3x:    mov dl,al        ; Save al's char here
  199.         call cmgtch
  200.     inc cl            ; Read in another char
  201.     mov al,dl
  202.     cmp ah,'a'
  203.     jl cmky31
  204.     cmp ah,'z'+1
  205.     jns cmky31
  206.     and ah,137O
  207. cmky31: cmp ah,esc+80H        ; Escape Recognition (escape w/minus bit on)?
  208.     je cmky3y
  209.     cmp ah,'?'+80H        ; A question mark?    [3]
  210.     je cmky3y
  211.     cmp ah,' '+80H        ; A space?
  212.     je cmky3y
  213.     cmp ah,cr+80H        ; Carriage return?
  214.     je cmky3y
  215.     jmp cmky38
  216. cmky3y:    mov comand.cmkptr,bx    ; Save bx here
  217.     mov comand.cmsiz,cx    ; Save size info
  218.     mov comand.cmchr,ah    ; Save char for latter
  219.     call cmambg        ; See if input is ambiguous or not
  220.      jmp cmky32        ; Succeeded (not ambiguous)
  221.     mov ah,comand.cmchr
  222.     cmp ah,esc+80H        ; Escape?
  223.     je cmky3z
  224.     cmp ah,'?'+80H        ; maybe question mark?
  225.     je cmkyj1        ; yes, go handle
  226.     jmp cmky41        ; Else fail
  227. cmky3z:    mov ah,conout        ; Ring a bell
  228.     mov dl,bell
  229.     int dos
  230.     mov bx,comand.cmcptr    ; Move pointer to before the escape
  231.     dec bx
  232.     mov comand.cmcptr,bx
  233.     mov comand.cmdptr,bx
  234.     dec comand.cmccnt    ; Decrement char count
  235.     mov bx,comand.cmkptr    ; Failed - pretend user never typed ...
  236.     mov cx,comand.cmsiz    ; ... in a char
  237.     dec cl            ; Don't count the escape
  238.     dec bx
  239.     mov comand.cmaflg,0    ; Reset the action flag
  240.     jmp cmky3        ; Keep checking
  241. ; ambiguous.  Print out all the keywords that match
  242. cmkyj1:    mov dx,offset cmin01
  243.     mov ah,prstr
  244.     int dos
  245.     mov bx,comand.cmkptr    ; this is current keyword
  246.     mov cx,comand.cmsiz    ; we are cl chars into it
  247.     mov ch,0
  248.     sub bx,cx        ; back up to beginning
  249.     inc bx            ; not counting ?
  250.     mov comand.cmkptr,bx    ; save beginning of kw
  251. cmkyj2:    mov dl,tab        ; put a tab before each keyword
  252.     mov ah,conout
  253.     int dos
  254.     mov dx,comand.cmkptr    ; get current keyword
  255.     mov ah,prstr
  256.     int dos            ; print it
  257.     mov bx,comand.cmkptr    ; get keyword back
  258.     dec bx
  259.     mov al,[bx]        ; get length
  260.     mov ah,0
  261.     add ax,5        ; skip length, $, value, next length
  262.     add bx,ax        ; this is next keyword
  263.     mov si,bx
  264.     mov di,comand.cmkptr    ; compare with last keyword
  265.     mov comand.cmkptr,bx    ; update this
  266.     mov cx,comand.cmsiz
  267.     dec ch            ; are we at end of table?
  268.     jl cmkyj3        ; yes, don't go on
  269.     mov comand.cmsiz,cx    ; else update count
  270.     mov ch,0
  271.     dec cl            ; this includes ?
  272.     jcxz cmkyj2        ; empty, just print it
  273.     repe cmpsb        ; compare to previous string
  274.     je cmkyj2        ; same, go print this one
  275. cmkyj3:    jmp cmky50        ; else go finish up
  276.  
  277. cmky32: mov cx,comand.cmsiz    ; Restore info
  278.     mov bx,comand.cmkptr    ; Our place in the keyword table
  279.     cmp comand.cmchr,0A0H    ; Space?
  280.     je cmky35
  281.     cmp comand.cmchr,0BFH    ; Question mark?     [3]
  282.     je cmky35
  283.     cmp comand.cmchr,8DH    ; Carriage return?
  284.     je cmky35
  285.     dec comand.cmcptr    ; Pointer into buffer of input
  286.     mov dx,comand.cmcptr
  287. cmky33:    mov ah,[bx]        ; Get next char in keyword
  288.     cmp ah,'$'        ; Are we done yet?
  289.     jz cmky34
  290.     mov di,dx
  291.     mov [di],ah
  292.     inc bx
  293.     inc dx
  294.     inc comand.cmccnt
  295.     jmp cmky33
  296. cmky34:    mov ah,' '
  297.     mov di,dx
  298.     mov [di],ah        ; Put a blank in the buffer
  299.     inc dx
  300.     mov cx,comand.cmcptr    ; Remember where we were
  301.     mov comand.cmcptr,dx    ; Update our pointers
  302.     mov comand.cmdptr,dx
  303.     mov ah,'$'
  304.     mov di,dx
  305.     mov [di],ah        ; Add '$' for printing
  306.     mov ah,prstr
  307.     mov dx,cx        ; Point to beginning of filled in data
  308.     int dos
  309.     inc bx            ; Point to address we'll need
  310.     mov bx,[bx]
  311.     mov comand.cmaflg,0    ; Turn off action flag
  312.     jmp rskp
  313.  
  314. cmky35:    inc bx
  315.     mov ah,[bx]        ; Find end of keyword. 
  316.     cmp ah,'$'
  317.     jne cmky35    
  318.     inc bx
  319.     mov bx,[bx]        ; Address of next routine to call
  320. ;    mov comand.cmaflg,0    ; Zero the action flag
  321.     jmp rskp
  322.  
  323. cmky38:    cmp ah,al
  324.     je cmky39
  325.         jmp cmky6        ; Go to end of keyword and try next
  326. cmky39:    jmp cmky3        ; Check next letter
  327.            
  328. cmky4:  and ah,7FH       ; Turn off minus bit
  329.         cmp ah,'?'       ; Need help?
  330.         je cmky5
  331.     cmp ah,' '        ; Just a space - no error
  332.     je cmky51
  333.     cmp ah,cr
  334.     je cmky51
  335.     cmp ah,tab
  336.     je cmky51 
  337.     cmp ah,esc        ; Ignore escape?
  338.     je cmky43
  339. cmky41: mov ah,prstr
  340.         mov dx,offset cmer03
  341.         int dos
  342.         jmp prserr       ; Parse error - give up
  343.  
  344. cmky43:    mov ah,conout        ; Ring a bell
  345.     mov dl,bell
  346.     int dos
  347.     mov bx,comand.cmcptr
  348.     dec bx
  349.     mov comand.cmcptr,bx
  350.     mov comand.cmdptr,bx
  351.     dec comand.cmccnt    ; Don't count the escape
  352.     mov comand.cmaflg,0    ; Reset action flag
  353.     inc ch            ; Account for a previous 'dec'
  354.     jmp cmky1        ; Start over
  355.  
  356. cmky5:    inc bx            ; point to actual keyword
  357.     mov comand.cmkptr,bx    ; remember current kw
  358.     mov cl,1        ; code above expects to count ?
  359.     mov comand.cmsiz,cx    ; and size
  360.     mov dx,comand.cmhlp
  361.     or dx,dx        ; was any help given?
  362.     jnz cmky5a        ; yes, use it
  363.     jmp cmkyj1        ; else make our own message
  364. cmky5a:    mov ah,prstr
  365.         int dos
  366. cmky50:    mov ah,prstr
  367.     mov dx,offset crlf
  368.     int dos
  369.     mov dx,comand.cmprmp    ; Address of prompt
  370.     int dos
  371.     mov bx,comand.cmdptr    ; Get pointer into buffer
  372.     mov al,'$'
  373.     mov [bx],al        ; Add dollar sign for printing
  374.     mov dx,offset comand.cmdbuf
  375.     int dos
  376.     dec comand.cmcptr    ; Don't keep it in the buffer
  377.     dec comand.cmccnt    ; Don't conut it
  378.     mov comand.cmaflg,0     ; Turn off the action flag
  379.         jmp repars
  380.  
  381. cmky51:    cmp comand.cmcr,1    ; Are bare CR's allowed?
  382.     je cmky52        ; Yes
  383.     mov ah,prstr
  384.     mov dx,offset cmer04    ; Complain
  385.     int dos
  386. cmky52:    jmp prserr
  387.  
  388. cmky6:  inc bx        ; Find end of keyword
  389.         mov al,[bx]
  390.         cmp al,'$'
  391.         jne cmky6             
  392.         inc bx        ; Beginning of next command
  393.         inc bx
  394.         inc bx
  395.     mov dx,comand.cmsptr    ; Get old cmdptr
  396.     mov comand.cmdptr,dx    ; Restore
  397.     mov comand.cmsflg,0FFH
  398.         jmp cmky1        ; Keep trying
  399.  
  400. cmky7:  call cmgtch      ; Get char
  401.     cmp ah,0
  402.     js cmky71        ; Ok if a terminator
  403.         dec bx
  404.         jmp cmky6        ; No match - try next keyword
  405. cmky71: inc bx        ; Get necessary data
  406.         mov bx,[bx]
  407.     cmp ah,9BH        ; An escape?
  408.     jne cmky72
  409.     mov ah,prstr
  410.     mov dx,offset prsp      ; Print a space
  411.     int dos
  412.     mov di,comand.cmcptr
  413.     dec di
  414.     mov ah,20H
  415.     mov [di],ah        ; Replace escape char with space
  416.     mov comand.cmaflg,0
  417.     mov comand.cmsflg,0FFH    ; Pretend they typed a space
  418. cmky72: jmp rskp
  419.  
  420. ; See if keyword is unambiguous or not from what the user has typed in
  421.  
  422. cmambg:    cmp ch,0        ; Any keywords left to check?
  423.     jne cmamb0
  424.     ret            ; If not then not ambiguous
  425. cmamb0:    inc bx            ; Go to end of keyword ..
  426.     mov al,[bx]        ; So we can check the next one
  427.     cmp al,'$'
  428.     jne cmamb0
  429.     add bx,4        ; Point to start of next keyword
  430.     dec cl            ; Don't count escape
  431.     mov dx,comand.cmsptr    ; Buffer with input typed by user
  432. cmamb1:    mov ah,[bx]        ; Keyword char.    
  433.     mov di,dx
  434.     mov al,[di]        ; Input char
  435.     cmp al,'a'        ; Do capitalizing
  436.     jl cmam11
  437.     cmp al,'z'+1
  438.     jns cmam11
  439.     and al,137O
  440. cmam11:    cmp ah,al        ; Keyword bigger than input (alphabetically)?
  441.     jle cmamb2        ; No - keep checking
  442.     ret            ; Yes - not ambiguous
  443. cmamb2:    inc bx            ; Advance one char
  444.     inc dx
  445.     dec cl
  446.     jnz cmamb1
  447.     jmp rskp        ; Fail - it's ambiguous
  448.  
  449. cmifil:    mov hlpmsg,bx        ; Address of help message
  450.     mov bx,dx        ; Get the fcb address in bx
  451.         mov comand.cmfcb,bx     ; Save it
  452.         mov ch,0        ; Initialize char count
  453.         mov ah,0
  454.         mov [bx],ah        ; Set the drive to default to current
  455.     inc bx
  456.         mov comand.cmfcb2,bx
  457.         mov cl,' '
  458. cmifi0: mov [bx],cl        ; Blank the FCB
  459.         inc bx
  460.         inc ah
  461.         cmp ah,0BH        ; Twelve?
  462.         jl cmifi0
  463. cmifi1: call cmgtch      ; Get another char
  464.         cmp ah,0        ; Is it an action character
  465.     js cmif1x        ; Jump out of range. [21a]
  466.         jmp cmifi2        ; Ditto. [21a]
  467. cmif1x: and ah,7FH       ; Turn off the action bit. [21a]
  468.         cmp ah,'?'       ; A question mark?
  469.         jne cmif12
  470.         mov al,0
  471.         mov comand.cmaflg,al    ; Blank the action flag
  472.         dec comand.cmcptr       ; Decrement the buffer pointer
  473.     dec comand.cmccnt    ; Decrement count
  474.     mov ah,prstr
  475.     mov dx,hlpmsg        ; Help  message
  476.     int dos
  477.     mov dx,offset crlf
  478.     int dos
  479.     mov dx,comand.cmprmp
  480.     int dos
  481.     mov bx,comand.cmdptr
  482.     mov al,'$'
  483.     mov [bx],al        ; Put in dollar sign for printing
  484.     mov dx,offset comand.cmdbuf
  485.     int dos
  486.     jmp repars
  487. cmif12: cmp ah,esc        ; An escape?
  488.     je cm12x
  489.         jmp cmif13
  490. cm12x:    mov comand.cmaflg,0    ; Turn off the action flag
  491.     dec comand.cmcptr    ; Move pointers to before the escape
  492.     dec comand.cmdptr
  493.     dec comand.cmccnt    ; Decrement char count
  494.     mov comand.cmchr,ch    ; Save current character count
  495.     cmp ch,9        ; Past '.'?
  496.          jl cmf120        ; No
  497.     dec ch            ; Yes, don't count point
  498. cmf120:    mov di,comand.cmfcb2    ; Fill the rest with CP/M wildcards
  499.     mov ah,'?'
  500.  
  501. cmf121:    cmp ch,11        ; Done?
  502.      jge cmf122        ; Yes
  503.     mov [di],ah
  504.     inc di
  505.     inc ch
  506.     jmp cmf121
  507.  
  508. cmf122: mov ah,sfirst        ; Find first matching file?
  509.     mov dx,comand.cmfcb    ;[jd] use pointer to PASSED fcb
  510.     int dos
  511.     cmp al,0FFH        ; Any found?
  512.     jne cmf123        ; Yes
  513.      jmp cmf12b        ; No, lose
  514. cmf123:    mov di,offset filbuf    ; Copy first file spec from DTA to buffer
  515.     mov bx,offset DTA+1
  516.     mov cl,11
  517.     call fcbcpy
  518.     mov di,offset filbuf+10H ; Get another copy (if not ambiguous)
  519.     mov bx,offset DTA+1
  520.     mov cl,11
  521.     call fcbcpy
  522.     mov ah,snext        ; More matching specs?
  523.     mov dx,comand.cmfcb    ;[jd] use PASSED fcb..
  524.     int dos
  525.     cmp al,0FFH
  526.      je cmf124        ; Only one
  527.     mov di,offset filbuf+10H ; Copy second file spec
  528.     mov bx,offset DTA+1
  529.     mov cl,11
  530.     call fcbcpy
  531.  
  532. cmf124:    mov si,offset filbuf    ; Start comparing file names
  533.     mov bx,offset filbuf+10H
  534.     mov di,comand.cmcptr    ; Command buffer pointer
  535.     mov cl,comand.cmchr    ; Bypass characters typed
  536.     cmp cl,9        ; Past '.'?
  537.      jl cmf125        ; No
  538.     dec cl            ; Yes, don't count point
  539. cmf125:    mov ch,0        ; Adjust pointers
  540.     add si,cx
  541.     add bx,cx
  542.     mov ch,cl        ; Update character count
  543.  
  544. cmf126:    cmp ch,11        ; All done?
  545.     jne cmf127        ; No
  546.      jmp cmf12a        ; Yes
  547. cmf127:    cmp ch,8        ; End of file name?
  548.      jne cmf128        ; No
  549.     cmp comand.cmchr,9    ; Exactly at point?
  550.      je cmf128        ; Yes, don't output a second point
  551.     mov ah,'.'        ; Output separator
  552.     mov [di],ah
  553.     inc di
  554.     inc comand.cmccnt
  555. cmf128:    mov ah,[si]        ; Get a character from first file spec
  556.     inc si
  557.     mov al,[bx]        ; Get another from second spec
  558.     inc bx
  559.     cmp ah,al        ; Compare
  560.      jne cmf12a        ; Ambiguous
  561.     inc ch            ; Same, count
  562.     cmp ah,' '        ; Blank?
  563.      je cmf129        ; Yes, don't output
  564.     mov [di],ah
  565.     inc di
  566.     inc comand.cmccnt
  567. cmf129:    jmp cmf126        ; Repeat
  568.  
  569.  %OUT >> About half way through source file
  570.  
  571. cmf12a:    mov comand.cmchr,ch    ; Save count of characters processed
  572.     mov ah,'$'        ; Put terminator into buffer
  573.     mov [di],ah
  574.     mov comand.cmcptr,di    ; Save pointer for recognized characters
  575.     mov ah,prstr
  576.     mov dx,comand.cmdptr
  577.     int dos
  578.     mov ch,comand.cmchr    ; Characters processed
  579.     cmp ch,11        ; Complete file name
  580.      je cmf12c        ; Yes, don't beep
  581.  
  582. cmf12b:    mov ah,conout        ; Beep, if not recognized
  583.     mov dl,bell
  584.     int dos            ; Ring the bell
  585. cmf12c:    jmp repars
  586.  
  587. cmif13: mov ah,ch        ; It must be a terminator
  588.         cmp ah,0        ; Test the length of the file name
  589.     jnz cmf3x
  590.     cmp comand.cmcr,1    ; Is zero length OK? [21a]
  591.     je cmf3z        ; Return successfully. [21a]
  592.         jmp cmifi9       ; If zero complain
  593. cmf3x:  cmp ah,0DH
  594.         js cmf3y
  595.     jmp cmifi9       ; If too long complain
  596. cmf3y:  jmp rskp        ; Otherwise we have succeeded
  597. cmf3z:    push es
  598.     mov ax,ds
  599.     mov es,ax
  600.     mov di,comand.cmfcb
  601.     inc di
  602.     mov cx,11
  603.     mov al,'?'
  604.     repne stosb
  605.     pop es
  606.     mov flags.wldflg,0FFH    ; Remember we had a wildcard
  607.     jmp rskp
  608. cmifi2: cmp ah,'.'
  609.         jne cmifi3
  610.         inc ch
  611.         mov ah,ch
  612.         cmp ah,1H        ; Any chars yet?
  613.        jnz cmf2x
  614.     jmp cmifi9        ; No, give error
  615. cmf2x:  cmp ah,0AH        ; Tenth char?
  616.        js cmf2y
  617.     jmp cmifi9       ; Past it, give an error
  618. cmf2y:  mov dl,9H
  619.         mov dh,0
  620.         mov bx,comand.cmfcb
  621.         add bx,dx        ; Point to file type field
  622.         mov comand.cmfcb2,bx
  623.         mov ch,9H        ; Say we've gotten nine
  624.         jmp cmifi1       ; Get the next char
  625. cmifi3: cmp ah,':'
  626.         jne cmifi4
  627.         inc ch
  628.         cmp ch,2H        ; Is it in right place for a drive?
  629.     je cmif3x
  630.         jmp cmifi9       ; If not, complain
  631. cmif3x: mov ch,0        ; Reset char count
  632.     mov flags.droflg,1    ; Override default drive. [21a]
  633.     mov flags.nmoflg,0    ; Not so fast. [21a]
  634.     mov bx,comand.cmfcb2
  635.     mov al,':'        ; Use for parsing drive name
  636.     mov [bx],al
  637.     dec bx            ; Point to drive spec
  638.     mov si,bx
  639.     push es
  640.     mov ax,ds
  641.     mov es,ax
  642.     mov di,offset tbuff    ; Borrow this buffer
  643.     mov ah,prsfcb
  644.     int dos
  645.     pop es
  646.     cmp al,0        ; OK return code?
  647.     je cmif3y        ; Yes, keep going
  648. ;        mov ah,[bx]        ; Get the drive name
  649. ;        sub ah,'@'       ; Get the drive number
  650. ;    cmp ah,drives        ; Did user specify a non-existant drive? [21a]
  651. ;    jle cmif3y        ; Nope, so continue. [21a]
  652.     mov dx,offset cmer07    ; Fail with this error message. [21a]
  653.     jmp cmif9x        ; [21a]
  654. cmif3y:    mov comand.cmfcb2,bx    ; Put rest of filename starting here. [21a]
  655.     mov ah,[bx]        ; Pick up drive specified
  656.     sub ah,'@'        ; Get real value
  657.     mov bx,comand.cmfcb
  658.         mov [bx],ah        ; Put it in the fcb
  659.     push bx
  660.     mov al,' '        ; Overwrite the drive and ":"
  661.     inc bx
  662.     mov [bx],al
  663.     inc bx
  664.     mov [bx],al
  665.     pop bx
  666.         jmp cmifi1
  667. cmifi4: cmp ah,'*'
  668.         jne cmifi7
  669.     cmp comand.cmrflg,1    ; In receive mode?  [21a]
  670.     jne cmif4x        ; Jump out of range. [21a]
  671.     mov dx,offset cmer06    ; Set the error message. [21a]
  672.     jmp cmif9x        ; Fail - no wildcard allowed. [21a]
  673. cmif4x: mov ah,ch        ; [21a]
  674.         cmp ah,8H        ; Is this in the name or type field?
  675.         jns cmifi5       ; Type
  676.         mov cl,8H        ; Say we have eight chars
  677.         js cmifi6        ; Name field
  678.         jmp cmifi9        ; If its where the dot should be give up
  679. cmifi5: mov cl,0CH       ; Three chars
  680. cmifi6: mov flags.wldflg,0FFH    ; Remember we had a wildcard
  681.     mov bx,comand.cmfcb2    ; Get a pointer into the FCB
  682.         mov ah,'?'
  683.         mov [bx],ah        ; Put a question mark in
  684.         inc bx
  685.         mov comand.cmfcb2,bx
  686.         inc ch
  687.         mov ah,ch
  688.         cmp ah,cl
  689.         jl cmifi6        ; Go fill in another
  690.         jmp cmifi1       ; Get the next char
  691. cmifi7: cmp ah,03DH        ; Equals sign (wildcard)?
  692.     jne cmif7x
  693.     cmp comand.cmrflg,1    ; In receive mode?  [21a]
  694.     jne cmif7y        ; No, so it's ok. [21a]
  695.     mov dx,offset cmer06    ; Set the error message. [21a]
  696.     jmp cmif9x        ; Fail - no wildcard allowed. [21a]
  697. cmif7y:    mov ah,'?'        ; New label. [21a]
  698.     mov flags.wldflg,0FFH    ; Say we have a wildcard
  699.     jmp cmifi8        ; Put into FCB
  700. cmif7x:    cmp ah,'0'
  701.         jl cmif8x
  702.         cmp ah,'z'+1
  703.         jns cmif8x
  704.         cmp ah,'A'        ; Don't capitalize non-alphabetics
  705.         jl cmifi8
  706.         and ah,137O      ; Capitalize
  707. cmifi8: mov bx,comand.cmfcb2    ; Get the pointer into the FCB
  708.         mov [bx],ah      ; Put the char there
  709.         inc bx
  710.         mov comand.cmfcb2,bx
  711.     mov flags.nmoflg,1    ; Overriding name from host. [21a]
  712.         inc ch
  713.         jmp cmifi1
  714.  
  715. cmif8x:    push es
  716.     mov cx,ds
  717.     mov es,cx        ; Scan uses ES register
  718.     mov di,offset spchar    ; Special chars
  719.     mov cx,spclen        ; How many of them
  720.     cmp dosnum,0        ; Under version 2.0
  721.     je cmif8y
  722.     mov di,offset spchar2
  723.     mov cx,spc2len
  724. cmif8y:    mov al,ah        ; Char is in al
  725.     repnz scasb        ; Search string for input char
  726.     cmp cx,0        ; Was it there?
  727.     pop es
  728.     jnz cmifi8
  729.  
  730. cmifi9: mov dx,offset cmer02
  731. cmif9x:    mov ah,prstr
  732.         int dos
  733.     mov flags.droflg,0    ; Not overriding drive. [21a] 
  734.     mov flags.nmoflg,0    ; Or name to save file under. [21a]
  735.     mov comand.cmrflg,0    ; Reset this flag too. [21a]
  736.         ret
  737.  
  738. cmofil: jmp cmifil       ; For now, the same as CMIFI
  739.  
  740. ; Parse arbitrary text up to a CR.  Put chars into data buffer sent to
  741. ; the host (pointed to by BX).   Called with text of help message in DX
  742. ; Return updated pointer in BX and input size in AH
  743.  
  744. cmtext:    mov comand.cmptab,bx    ; Save pointer to data buffer.   [8 start]
  745.     mov cmthlp,dx        ; Save the help message
  746.     mov cl,0        ; Init the char count
  747. cmtxt1:    mov comand.cmsflg,0    ; Get all spaces. [25]
  748.     call cmgtch        ; Get a char
  749.     test ah,80H        ; is high-order bit on?
  750.     jz cmtxt5        ; Nope, put into the buffer
  751.     and ah,07FH
  752.     cmp ah,' '
  753.     je cmtxt5
  754.     cmp ah,esc        ; An escape?
  755.     jne cmtxt2
  756.     mov ah,conout
  757.     mov dl,bell        ; Ring a bell
  758.     int dos
  759.     mov comand.cmaflg,0    ; Reset action flag
  760.     dec comand.cmcptr    ; Move pointer to before the escape
  761.     dec comand.cmdptr
  762.     dec comand.cmccnt    ; Decrement count
  763.     jmp cmtxt1        ; Try again
  764. cmtxt2:    cmp ah,'?'        ; Asking a question?
  765.     jz cmtx30
  766.     cmp ah,ff        ; Formfeed?
  767.     jne cmtx2x
  768.     call cmblnk
  769. cmtx2x: mov ah,cl        ; Return count in AH
  770.     mov bx,comand.cmptab    ; Return updated pointer
  771.     jmp rskp
  772. cmtx30:    mov comand.cmaflg,0    ; Reset action flag to zero
  773.     inc comand.cmdptr    ; count the ?
  774.     cmp cl,0        ; Is "?" first char?
  775.     jne cmtxt5        ; No, just add to buffer
  776.     mov ah,prstr        ; Else, give some help
  777.     mov dx,cmthlp        ; Address of help message
  778.     int dos
  779.         mov ah,prstr
  780.         mov dx,offset crlf      ; Print a crlf
  781.         int dos
  782.         mov ah,prstr
  783.         mov dx,comand.cmprmp    ; Reprint the prompt
  784.     int dos
  785.     dec comand.cmcptr    ; Don't keep it in the buffer
  786.     dec comand.cmccnt    ; Don't conut it
  787.     dec comand.cmdptr    ; don't count if printing help
  788.     mov bx,comand.cmdptr    ; Get the pointer into the buffer
  789.     mov byte ptr [bx],'$'
  790.     mov ah,prstr
  791.     mov dx,offset comand.cmdbuf    ;[fjj] RE-display command buffer
  792.     int dos                ; [fjj] AFTER adjusting pointers!!!
  793.     jmp cmtxt1        ; And keep going
  794. cmtxt5: inc cl            ; Increment the count
  795.     mov bx,comand.cmptab    ; Pointer into destination array
  796.     mov [bx],ah        ; Put char into the buffer
  797.     inc bx
  798.     mov comand.cmptab,bx
  799.     jmp cmtxt1                    ; [8 end]
  800.  
  801. cmgetc:    cmp taklev,0
  802.     jne cmget1
  803.     jmp cmge10            ; no take file, get from keyboard
  804. cmget1:    push bx
  805.     push si
  806.     mov bx,takadr
  807.     mov ax,[bx].takcnt
  808.     or ax,[bx].takcnt+2
  809.     jnz cmget5
  810. cmget2:    mov al,byte ptr [bx].takfcb    ; get first byte of fcb
  811.     cmp al,0ffh            ; is it really a macro?
  812.     je cmget4            ; yes, better not try to close it
  813.     cmp al,0feh            ; or maybe a file handle?
  814.     je cmget3            ; yes, close w/2.0 call
  815.     mov ah,closf
  816.     lea dx,[bx].takfcb
  817.     int dos
  818.     jmp short cmget4            ; skip over alternate close
  819. cmget3:    mov bx,word ptr [bx].takfcb+1    ; this is where file handle is stored
  820.     mov ah,close2            ; use 2.0 close
  821.     int dos
  822. cmget4:    dec taklev
  823.     sub takadr,size takinfo
  824.     pop si
  825.     pop bx
  826.     mov al,cr        ; end with carriage return..
  827.     ret
  828.     
  829. cmget5:    cmp [bx].takchl,0    ; Any chars left in buffer?
  830.     jne cmget6
  831.     call takrd
  832. cmget6:    dec [bx].takchl
  833.     sub [bx].takcnt,1    ; DEC doesn't set carry!!
  834.     sbb [bx].takcnt+2,0
  835.     mov si,[bx].takptr
  836.     lodsb
  837.     mov [bx].takptr,si
  838.     cmp al,ctlz        ; maybe control-z?
  839.     je cmget2        ; yes, close take file (has to be before pops)
  840.     pop si
  841.     pop bx
  842.     cmp al,lf        ; linefeed?
  843.     jne cmget7
  844.     cmp flags.takflg,0
  845.     je cmgetc        ; yes, ignore it
  846. cmget7:
  847.     cmp flags.takflg,0    ; Echo contents of take file?
  848.     je cmget8
  849.     push dx
  850.     mov dl,al
  851.     mov ah,conout
  852.     int dos
  853.     pop dx
  854. cmget8:    ret            ; else just return..
  855.  
  856. cmge10:    cmp In_menu_mode, 0    ; Are we in menu mode?
  857.      je KER_1        ;  No
  858.  
  859. ; In menu mode and not reading from a take file, so it must be time
  860. ;  to redisplay the menu ..
  861.  
  862.     call Quick_menu        ; Display the menu
  863.      nop
  864.      nop
  865.      nop
  866.  
  867.     mov ah, PrStr        ; Type string
  868.     mov dx, OFFSET CrLf    ; CRLF
  869.     int Dos            ; Makes screen look nicer
  870.  
  871.     jmp CmGetC        ; Go get the first character from the newly
  872.                 ;  created Pseudo-Macro
  873.  
  874. KER_1:    cmp PC_Type, 2        ; Running on a DEC Rainbow
  875.      jNE IBMpcs        ; No - skip Rainbow code
  876.  
  877. ; Machine-specific code for DEC Rainbow
  878.  
  879. cmge10_b:
  880.     push es            ; Firmware eats this one
  881.     Mov di, 6
  882.     Int 18h            ; Get level 1 char
  883.     pop es            ; Restore register
  884.     cmp cl, 0ffh        ; Did we get a char?
  885.      jE Check_for_DO    ; Yes - go check it
  886.     cmp cl, 0        ; No - 
  887.      jE cmge10_b        ;  keep looking for one
  888.     cmp cl, 1        ; Level 2 char around? (probably type-ahead)
  889.      jE IBMpcs        ; Yes - go handle it
  890.     jmp cmge10_b        ; No - we've checked all possibilities,
  891.                 ;  something fishy goin' on - try again
  892. Check_for_DO:
  893.     test ah, 1        ; Function flag on?
  894.      jZ No_DO        ; No - this can't be the DO key
  895.     cmp al, 1        ; Yes -
  896.                 ;  but is this really the DO key?
  897.      jE Quick_Term        ; Yes - it was the DO key, go into 
  898.                 ;  terminal emulation mode
  899.                 ; No - some other function key was pressed
  900.     Call Check_for_sensible_func_keys   ; If Keypad number or '-', ','
  901.                         ;  '.', or ENTER
  902.                         ;  translate to sensible scan code
  903.     jmp No_DO        ; If normal return, a sensible key was found
  904.     Call Beep        ; Else if skip return some nonsensible
  905.                 ;  function key was pressed - make a beep
  906.     jmp cmge10_b        ;  and try again   
  907.  
  908. Quick_Term:
  909.     mov ah, PrStr        ; Code to type a string
  910.     mov dx, OFFSET DO_str    ; Mark that the user hit the DO key
  911.     int Dos
  912.  
  913.     jmp Enter_TE_mode    ; Enter Terminal Emulation mode
  914.  
  915. No_DO:    mov ah, coninq        ; Make it look like a generic DOS function call
  916.     jmp cmge11_A0        ;  and join common code with char in al
  917.  
  918. ; Assume at this point that we are an IBM PC or close clone
  919.  
  920. IBMpcs:    mov ah,coninq        ; Get a char
  921.     cmp flags.debug,0    ; in debug mode?
  922.     je cmge11        ; yes, go on
  923.     mov ah,8        ; else use read that recognizes ^C
  924. cmge11:    int dos
  925. cmge11_A0:
  926.     push ax            ; save the char
  927.  
  928. ; See if what we have is a special character
  929.  
  930.     or al, al        ; Is this char a zero?
  931.      jnz cmge11_a        ;  No, continue
  932.  
  933.     mov ah, 8        ; Get another char
  934.     int dos            ;  to see what we really got the first time
  935.  
  936. ; Maybe quick entry into Terminal Emulation mode
  937.  
  938.     cmp al, 63        ; Is it the code for F5?
  939.      je Is_F5        ;  Yes
  940.  
  941.     cmp al, 108        ; Is it the code for ALT F5?
  942.      je Is_F5        ;  Yes
  943.  
  944.     cmp al, 110        ; ALT F7 (exit) ?
  945.      je Is_ALT_F7        ;  Yes
  946.  
  947.     cmp al, 111        ; ALT F8 (push) ?
  948.      je Is_ALT_F8        ;  Yes
  949.  
  950.     jmp Ignore_key        ; Not a key we work with
  951.  
  952. Is_F5:    mov ah, PrStr        ; Code to type a string
  953.     mov dx, OFFSET F5_str    ; Mark that the user hit the F5 key
  954.     int Dos
  955.  
  956. Enter_TE_mode:
  957.     mov sp, OldStk        ; Pick up the value SP had before COMND
  958.                 ;  was called
  959.  
  960.     mov ax, OFFSET KrmRet    ; The return addr that would have been set
  961.     push ax            ; Put it on the stack
  962.     jmp Telnet2        ; Jump quickly into terminal emulation mode
  963.  
  964. Is_ALT_F7:
  965.     mov sp, OldStk        ; Pick up the value SP had before COMND
  966.                 ;  was called
  967.  
  968.     mov flags.extflg, 0FFh    ; Flag that we are leaving
  969.     mov ax, OFFSET KrmRet    ; The return addr that would have been set
  970.     push ax            ; Put it on the stack
  971.     jmp RSkp        ; Exit the program
  972.  
  973. Is_ALT_F8:
  974.     mov sp, OldStk        ; Pick up the value SP had before COMND
  975.                 ;  was called
  976.  
  977.     mov ax, OFFSET KrmRet    ; The return addr that would have been set
  978.     push ax            ; Put it on the stack
  979.     jmp Quick_Push        ; Push out of the program
  980.  
  981. Ignore_key:
  982.     pop ax            ; Fix up stack
  983.     jmp cmge10        ;  Then go get a new key
  984.  
  985. cmge11_a:
  986.     cmp al,bs        ; backspace?
  987.     je cmge13        ; yes, skip echo
  988.     cmp al,' '        ; printable?
  989.     jae cmge12        ; yes, no translation needed
  990.     cmp al,cr        ; this is printable
  991.     jne cmge11_b
  992.  
  993.     mov dl, al        ; Hit CR, first echo it
  994.     mov ah, conout
  995.     int Dos
  996.     mov al, Lf        ; Then type a LF
  997.     jmp SHORT cmge12
  998.  
  999. cmge11_b:
  1000.     cmp al,lf
  1001.     je cmge12
  1002.     cmp al,tab
  1003.     je cmge12
  1004.     mov al,' '        ; else echo a space
  1005. cmge12:    mov dl,al        ; put char here
  1006.     mov ah,conout
  1007.     int dos            ; echo it ourselves..
  1008. cmge13:    pop ax            ; and return it
  1009.     cmp al,'C'-40H        ; control-C?
  1010.     je cmge15        ; yes, go handle
  1011.     cmp al,tab
  1012.     jne cmge14
  1013.     mov al,' '
  1014. cmge14:    ret
  1015.  
  1016.     PUBLIC cmge15
  1017.  
  1018. cmge15:    mov dx,offset ctcmsg
  1019.     mov ah,prstr
  1020.     int dos
  1021.     mov flags.cxzflg,'C'    ; remember ^C'd
  1022.     mov sp,cmdstk        ; restore command stack ptr
  1023.     ret            ; and fail
  1024.  
  1025. ; Come here is user types ^W when during input
  1026. cntrlw:    mov ah,prstr
  1027.     mov dx,offset escspc
  1028.     int dos
  1029.     dec comand.cmccnt    ; Don't include it in the count
  1030.     dec comand.cmcptr    ; Back up past the ^W
  1031.     mov cl,comand.cmccnt
  1032.     mov ch,0
  1033.     jcxz ctlw2
  1034.     pushf 
  1035.     push es
  1036.     std            ; Scan backwards
  1037.     mov ax,ds
  1038.     mov es,ax        ; Point to the data area
  1039.     mov di,comand.cmcptr    ; Looking from here
  1040.     dec di
  1041.     mov al,' '
  1042.     repe scasb        ; Look for non-space
  1043.     je ctlw1        ; All spaces, nothing else to do
  1044.     inc di            ; move back to non-space
  1045.     inc cx
  1046.     repne scasb        ; look for a space
  1047.     jne ctlw1        ; no space, leave ptrs alone
  1048.     inc di
  1049.     inc cx            ; skip back over space
  1050. ctlw1:    inc di
  1051.     mov comand.cmccnt,cl    ; update count
  1052.     mov cx,comand.cmcptr    ; remember old ptr
  1053.     mov comand.cmcptr,di    ; update pointer
  1054.     sub cx,di        ; this is characters moved
  1055.     mov al,bs        ; backspace
  1056.     cld
  1057.     mov di,offset tbuff    ; temporary buffer
  1058.     rep stosb        ; put enough spaces in
  1059.     mov byte ptr [di],'$'    ; end buffer
  1060.     mov dx,offset tbuff
  1061.     mov ah,prstr
  1062.     int dos            ; back up cursor
  1063.     call clearl        ; clear line
  1064.     pop es
  1065.     popf
  1066.     ret            ; and return
  1067. ctlw2:    mov ah,conout
  1068.     mov dl,bell
  1069.     int dos
  1070.     ret
  1071.  
  1072. cminbf:    push dx
  1073.     push bx
  1074.     mov cx,dx        ; Save value here too
  1075.     mov ah,comand.cmaflg    ; Is the action char flag set?
  1076.     cmp ah,0
  1077.     je cminb1
  1078.     jmp cminb9        ; If so get no more chars
  1079. cminb1: inc comand.cmccnt    ; Increment the char count
  1080.     call cmgetc
  1081.     mov ah,al        ; Keep char in 'ah'
  1082.     mov bx,comand.cmcptr    ; Get the pointer into the buffer
  1083.     mov [bx],ah        ; Put it in the buffer
  1084.     inc bx
  1085.     mov comand.cmcptr,bx
  1086.     cmp ah,'W'-64        ; Is it a ^W?
  1087.     jne cmnb11
  1088.     call cntrlw        ; Kill the previous word
  1089.     jmp repars
  1090. cmnb11:    cmp ah,25O        ; Is it a ^U?
  1091.     jne cminb2
  1092. cmnb12: call ctlu        ; Clear out the line
  1093.     mov ah,prstr
  1094.     mov dx,comand.cmprmp    ; Print the prompt
  1095.     int dos
  1096.     mov bx,offset comand.cmdbuf
  1097.     mov comand.cmcptr,bx    ; Reset the point to the start
  1098.     mov comand.cmccnt,0    ; Zero the count
  1099.     mov dx,cx        ; Preserve original value of dx
  1100.     jmp repars        ; Go start over
  1101. cminb2: cmp ah,bs           ; Or backspace?
  1102.     jz cminb3
  1103.     cmp ah,del        ; Delete?
  1104.     jne cminb4
  1105. cminb3:    call dodel        ; Delete a character
  1106.     mov ah,comand.cmccnt    ; Decrement the char count by two
  1107.     dec ah
  1108.     dec ah
  1109.     cmp ah,0            ; Have we gone too far?
  1110.     jns cmnb32        ; If not proceed
  1111.     mov ah,conout        ; Ring the bell
  1112.     mov dl,bell
  1113.     int dos
  1114.     jmp cmnb12        ; Go reprint prompt and reparse
  1115. cmnb32: mov comand.cmccnt,ah    ; Save the new char count
  1116.     mov ah,prstr        ; Erase the character
  1117.     mov dx,offset clrspc
  1118.     int dos
  1119.     mov bx,comand.cmcptr    ; Get the pointer into the buffer
  1120.     dec bx            ; Back up in the buffer
  1121.     dec bx
  1122.     mov comand.cmcptr,bx
  1123.     jmp repars        ; Go reparse everything
  1124. cminb4: cmp ah,'?'        ; Is it a question mark
  1125.     jz cminb6
  1126.     cmp ah,esc        ; Is it an escape?
  1127.     jz cminb8
  1128.     cmp ah,cr        ; Is it a carriage return?
  1129.     jz cminb5
  1130.     cmp ah,lf        ; Is it a line feed?
  1131.     jz cminb5
  1132.     cmp ah,ff        ; Is it a formfeed?
  1133.     jne cminb7
  1134.     call cmblnk
  1135.     call locate
  1136. cminb5: mov ah,comand.cmccnt    ; Have we parsed any chars yet?
  1137.     cmp ah,1
  1138.     jnz cminb6
  1139.     jmp prserr        ; If not, just start over
  1140. cminb6: mov ah,0FFH        ; Set the action flag
  1141.     mov comand.cmaflg,ah
  1142.     jmp cminb9
  1143.  
  1144.  
  1145. ; Got a non-action char, see if it would be the last in the buffer .
  1146. ;  If so, we trash it and beep, since we need to get an action char and
  1147. ;  there wouldn't be room for it otherwise
  1148.  
  1149. cminb7:    mov ah, comand.cmccnt    ; Get current char count
  1150.     cmp ah, cmdlen-1    ; Max'ed out?
  1151.      jnl cminb71        ;  Yeah, bomb it
  1152.  
  1153.     jmp cminb1        ; No sweat, go get another
  1154.  
  1155. cminb71:
  1156.     dec comand.cmccnt    ; About to blow buffer, back up by 1 char
  1157.     dec comand.cmcptr    ; Back up ptr too .
  1158.  
  1159.     mov ah, PrStr        ; Print the string
  1160.     mov dx, OFFSET ESCSpc    ; String containing BS, space, BS
  1161.     int DOS
  1162.  
  1163.     mov ah, conout        ; Then ring the bell
  1164.     mov dl,bell
  1165.     int DOS
  1166.  
  1167.     jmp cminb1        ; Get another char
  1168.  
  1169. cminb8: mov ah,prstr        ; Don't print the escape char
  1170.     mov dx,offset escspc
  1171.     int dos
  1172.     jmp cminb6
  1173.  
  1174. cminb9: pop bx
  1175.     pop dx
  1176.     ret
  1177.  
  1178. cmgtch: push cx
  1179.     push bx
  1180.     push dx
  1181. cmgtc1: mov ah,comand.cmaflg
  1182.     cmp ah,0            ; Is it set
  1183.     jne cmgt10
  1184.     call cminbf        ; If the action char flag is not set get more
  1185. cmgt10: mov bx,comand.cmdptr    ; Get a pointer into the buffer
  1186.     mov ah,[bx]        ; Get the next char
  1187.     inc bx
  1188.     mov comand.cmdptr,bx
  1189.     cmp ah,' '        ; Is it a space?
  1190.     jz cmgtc2
  1191.     cmp ah,tab        ; Or a tab?
  1192.     jne cmgtc3
  1193. cmgtc2: mov ah,comand.cmsflg    ; Get the space flag
  1194.     cmp ah,0        ; Was the last char a space?
  1195.     jne cmgtc1        ; Yes, get another char
  1196.     mov ah,0FFH        ; Set the space flag
  1197.     mov comand.cmsflg,ah
  1198.     mov ah,' '
  1199.     pop dx
  1200.     pop bx
  1201.     jmp cmgtc5
  1202. cmgtc3: mov al,0
  1203.     mov comand.cmsflg,al    ; Zero the space flag
  1204.     pop dx
  1205.     pop bx
  1206.     cmp ah,esc
  1207.     jz cmgtc5
  1208.     cmp ah,'?'        ; Is the user curious?
  1209.     jz cmgtc4
  1210.     cmp ah,cr
  1211.     jz cmgtc4
  1212.     cmp ah,lf
  1213.     jz cmgtc4
  1214.     cmp ah,ff
  1215.     je cmgtc4
  1216.     pop cx
  1217.     ret            ; Not an action char, just return
  1218. cmgtc4: dec comand.cmdptr
  1219. cmgtc5: or ah,80H        ; Make the char negative to indicate
  1220.     pop cx
  1221.     ret            ; it is a terminator
  1222. CMND    ENDP
  1223.  
  1224. ;    This address is jumped to on reparse
  1225.  
  1226. PARSE    PROC NEAR 
  1227. repars: mov sp,comand.cmostp   ; new sp <-- old sp
  1228.     mov bx,offset comand.cmdbuf
  1229.     mov comand.cmdptr,bx
  1230.     mov ah,0FFH
  1231.     mov comand.cmsflg,ah
  1232.     jmp comand.cmrprs    ; go back to reparse address 
  1233.  
  1234. ;    This address can be jumped to on a parsing error
  1235.  
  1236. prserr: mov sp,comand.cmostp    ; Set new sp to old one
  1237.     mov bx,offset comand.cmdbuf
  1238.     mov comand.cmcptr,bx    ; Initialize the command pointer
  1239.     mov comand.cmdptr,bx
  1240.     mov ah,0
  1241.     mov comand.cmaflg,ah    ; Zero the flags
  1242.     mov comand.cmccnt,ah
  1243.     mov comand.cmsflg,0FFH
  1244.     cmp taklev,0        ; in take cmd?
  1245.     jne prser1        ; yes, don't print prompt
  1246.     mov ah,prstr        ; Print the prompt
  1247.     mov dx,comand.cmprmp    ; Get the prompt
  1248.     int dos
  1249. ; Instead return to before the prompt call
  1250. prser1:    jmp comand.cmrprs
  1251. PARSE    ENDP
  1252.  
  1253. ;    FCB must be remembered if found "*" in filename.      [7 start]
  1254. ;    Copy from place addressed by BX to place addressed by DI
  1255. ;    Also use to get the filename to the FCB from the DTA
  1256.  
  1257. FCBCPY    PROC    NEAR
  1258.     push    es
  1259.     push    si
  1260.     mov    ax,ds
  1261.     mov    es,ax        ; make sure destination segment is correct
  1262.     mov    ch,0        ; high-order part of length
  1263.     jcxz    fcbcp1        ; zero argument (is this necessary???)
  1264.     mov    si,bx        ; this is source
  1265.     rep    movsb        ; copy the whole thing
  1266. fcbcp1:    pop    si
  1267.     pop    es
  1268.     ret            ; and return
  1269. FCBCPY    ENDP    
  1270.  
  1271. ; Rainbow-specific routine --
  1272. ;
  1273. ; During command screen input, the user may hit a keypad key desiring a 
  1274. ; certain number or a DASH, COMMA, PERIOD or ENTER
  1275. ; Since these are 'function keys' they have strange scan codes instead of 
  1276. ; the correct ASCII codes - we fix 'em up here
  1277.  
  1278. Check_for_sensible_func_keys    PROC    NEAR
  1279.     Cld            ; Set direction to from Left-to-Right
  1280.     Mov cx, Func_table_length    ; Length of translate table
  1281.     Mov di, OFFSET Sensible_func_keys    ; Address of lookup table
  1282.     RepNE ScasB                ; Look for function key value
  1283.     jE Found            ; Found it!
  1284.     jmp Rskp            ; Didn't find it - skip return
  1285.                 ; If found translate to correct ASCII code
  1286. Found:    Dec di            ; Make di point to found entry
  1287.     Sub di, OFFSET Sensible_func_keys  ; Turn address into array dimension
  1288.     Mov al, To_ASCII_scan_codes[di]    ; Translate function key to ASCII
  1289.     Ret                ; and return
  1290. Check_for_sensible_func_keys    ENDP
  1291.  
  1292. ; Jumping to this location is like retskp.  It assumes the instruction
  1293. ;   after the call is a jmp addr
  1294.  
  1295. RSKP    PROC    NEAR
  1296.     pop bp
  1297.     add bp,3
  1298.     push bp
  1299. ;    ret
  1300. RSKP    ENDP
  1301.  
  1302. ; Jumping here is the same as a ret
  1303.  
  1304. R    PROC    NEAR
  1305.     ret
  1306. R    ENDP
  1307.  
  1308. Code    ENDS
  1309.  
  1310.     END
  1311.